package net.funtip.jdbc;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import net.funtip.jdbc.entity.ParameterSet;
import net.funtip.jdbc.entity.QueryStatistic;

import org.joda.time.Duration;
import org.joda.time.Period;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;

public class QueryStatisticRenderer {

	public String getHTMLHeader() {
		return new String("<TR><TH>&nbsp;</TH><TH>Name</TH><TH>Count</TH><TH>Total Time</TH><TH>Avg. Time</TH><TH>Query Time</TH><TH>Next Time</TH><TH>Next Count</TH><TH>%</TH><TH>Params</TH></TR>");
	}

	public String getTextHeader() {
		return new String("Name                                                  |"+
		" Count |  Total Time |  Avg. Time  | Query Time | Next Time | Next Count");
	}

	public String toHTML(Collection<QueryStatistic> list) {
    	StringBuffer buf = new StringBuffer();
    	buf.append("<TABLE border=\"1\">");
    	buf.append("<tr><td colspan='4'></td>");
    	buf.append(getHTMLHeader());
    	int index = 0;
    	for (QueryStatistic qs: list) {
    		buf.append(toHTML(++index,qs));
    	}
    	buf.append("</TABLE>");
    	return buf.toString();
    }
    
    public String toString(Collection<QueryStatistic> list) {
        StringBuffer buf = new StringBuffer();
        buf.append("------------------------------------\n");
        buf.append(getTextHeader()+"\n");
        int index = 0;
        for (QueryStatistic qs: list) {
            buf.append(toStr(++index,qs)+"\n");
        }
        buf.append("------------------------------------\n");
        return buf.toString();
    }

	public String toHTML(int index, QueryStatistic qs) {
		return toHTML(index, qs, 10) ;
	}
	
	public String toHTML(int index, QueryStatistic qs, int maxParamDetail) {
		DecimalFormat df = new DecimalFormat("####0.000");
		StringBuffer buf = new StringBuffer();
    	PeriodFormatter pf = new PeriodFormatterBuilder()
    	.printZeroIfSupported() 
    	.appendHours().appendSeparatorIfFieldsBefore("h&nbsp;")
    	.minimumPrintedDigits(2)
    	.printZeroIfSupported()
    	.appendMinutes()
    	.appendSeparatorIfFieldsBefore("m&nbsp;")
    	.appendSeconds().toFormatter();


    	buf.append("<TR>\n");
		buf.append("<TD>"+index+"</TD>\n");
		buf.append("<TD>"+qs.getName()+"</TD>\n");
		buf.append("<TD>"+qs.getExecutionCount()+"</TD>\n");
		buf.append("<TD>"+pf.print(new Period(new Duration(qs.getExecutionTime()+qs.getNextTime())))+"</TD>\n");
		buf.append("<TD>"+df.format((qs.getExecutionTime()+qs.getNextTime())/(1000.0*qs.getExecutionCount()))+"</TD>\n");
		buf.append("<TD>"+df.format(qs.getExecutionTime()/1000.0)+"</TD>\n");
		buf.append("<TD>"+df.format(qs.getNextTime()/1000.0)+"</TD>\n");
		buf.append("<TD>"+qs.getNextCount()+"</TD>\n");
		buf.append("<TD><b>"+df.format(qs.getPercentage()/100.0)+"</b></TD>\n");
		buf.append("<TD>");
		Map<ParameterSet, Integer> map = qs.getParameterExecutionHistogram();

		Comparator<Integer> comparator= Collections.reverseOrder();
		SortedMap<Integer, List<ParameterSet>> sorted = new TreeMap<Integer, List<ParameterSet>>(comparator);
		for (ParameterSet key : map.keySet()) {
			int count = map.get(key);
			if (!sorted.containsKey(count))
				sorted.put(count, new ArrayList<ParameterSet>());
			sorted.get(count).add(key);
		}
		int ctr=0;
		buf.append("<b>"+map.size()+"</b> ");
		if (qs.getExecutionCount() != 0)
			buf.append(((100.0*map.size())/qs.getExecutionCount())+"%");
		buf.append("</br>");
		for(Integer count: sorted.keySet()) {
			List<ParameterSet> list = sorted.get(count);
			for (ParameterSet params : list) {
				buf.append("<nobr>(");
				buf.append(count+":");
				buf.append(params);
				buf.append(")</nobr><br>");
				ctr++;
				if (ctr==maxParamDetail)
					break;
			}
			if (ctr==maxParamDetail)
				break;
		}
		buf.append("</TD>");
		buf.append("</TR>\n");
		return buf.toString();
	}

	public String toStr(int index, QueryStatistic qs) {
		DecimalFormat df = new DecimalFormat("####0.000");
		StringBuffer buf = new StringBuffer();
		buf.append("");
		buf.append(""+index+" | ");
		buf.append(""+qs.getName()+" | ");
		buf.append(""+qs.getExecutionCount()+" | ");
		buf.append(""+df.format((qs.getExecutionTime()+qs.getNextTime())/1000.0)+" | ");
		buf.append(""+df.format((qs.getExecutionTime()+qs.getNextTime())/(1000.0*qs.getExecutionCount()))+" | ");
		buf.append(""+df.format(qs.getExecutionTime()/1000.0)+" | ");
		buf.append(""+df.format(qs.getNextTime()/1000.0)+" | ");
		buf.append(""+qs.getNextCount()+" | ");
		buf.append(""+df.format(qs.getPercentage()/100.0)+" | ");
		buf.append("\n");
		return buf.toString();
	}

}
